package com.ygqh.baby.service.impl;

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.constant.RedisConstant;
import com.ygqh.baby.model.VoteWorkListVo;
import com.ygqh.baby.model.YgVote;
import com.ygqh.baby.po.YgVoteWork;
import com.ygqh.baby.mapper.YgVoteWorkMapper;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.WxMpAuthorityService;
import com.ygqh.baby.service.YgVoteWorkService;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import com.ygqh.baby.po.YgVoteWorkExample;

/**
 * @author Ss
 */
@Service
public class YgVoteWorkServiceImpl implements YgVoteWorkService {

	private final ExecutorService executorService = Executors.newFixedThreadPool(3);

	@Autowired
	private YgVoteWorkMapper ygVoteWorkMapper;
	@Autowired
	private RedisDao redisDao;
	@Autowired
	private WxMpAuthorityService wxMpAuthorityService;

	@Override
	public List<YgVoteWork> find() {
		YgVoteWorkExample example = new YgVoteWorkExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return ygVoteWorkMapper.selectByExample(example);
	}

	@Override
	public int findCount() {
		YgVoteWorkExample example = new YgVoteWorkExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return ygVoteWorkMapper.countByExample(example);
	}

	@Override
	public YgVoteWork findById(Long id) {
		return ygVoteWorkMapper.selectByPrimaryKey(id);
	}

	@Override
	public int save(YgVoteWork ygVoteWork) {
		return ygVoteWorkMapper.insertSelective(ygVoteWork);
	}

	@Override
	public int update(YgVoteWork ygVoteWork) {
		return ygVoteWorkMapper.updateByPrimaryKeySelective(ygVoteWork);
	}

	@Override
	public int deleteSoft(Long[] ids) {
		Assert.notEmpty(ids);
		YgVoteWorkExample example = new YgVoteWorkExample();
		example.createCriteria().andIdIn(Arrays.asList(ids));
		YgVoteWork record = new YgVoteWork();
		record.setStatus(DataStatus.Delete);
		return ygVoteWorkMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int deleteSoft(Long id) {
		return this.deleteSoft(new Long[]{id});
	}

	@Override
	public int saveOrUpdate(YgVoteWork ygVoteWork) {
		int r;
		if (ygVoteWork.getId() != null) {
			r = this.update(ygVoteWork);
		} else {
			r = this.save(ygVoteWork);
		}
		return r;
	}

	@Override
	public ResultSet<YgVoteWork> search(QueryInfo queryInfo, String nickName, String voteBatchCode, CheckStatus checkStatus) {
		int count = ygVoteWorkMapper.countSuper(nickName, voteBatchCode, checkStatus);
		if (count == 0) {
			return new ResultSet<>();
		}
		List<YgVoteWork> list = ygVoteWorkMapper.selectSuper(queryInfo, nickName, voteBatchCode, checkStatus);
		return new ResultSet<>(count, list);
	}

	@Override
	public List<VoteWorkListVo> findList(QueryInfo queryInfo, String babyName, String voteBatchCode, CheckStatus checkStatus) {
		return ygVoteWorkMapper.selectList(queryInfo, babyName, voteBatchCode, checkStatus);
	}

	@Override
	public YgVoteWork findByVoteBatchCodeAndUserId(String voteBatchCode, Long userId, CheckStatus... checkStatus) {
		Assert.notNull(userId, "Param 'userId' must not be null");
		Assert.isTrue(StringUtils.isNotBlank(voteBatchCode), "Param 'voteBatchCode' must not be blank");
		return ygVoteWorkMapper.selectSingle(voteBatchCode, userId, checkStatus != null && checkStatus.length > 0 ? checkStatus : null);
	}

	@Override
	public YgVote getVoteInfoFromRedis() {
		String res = redisDao.get(RedisConstant.VOTE_BASE_INFO);
		if (StringUtils.isBlank(res)) {
			return null;
		}
		return JSON.parseObject(res, YgVote.class);
	}

	@Override
	public void updateVoteCountToUp(Long id) {
		ygVoteWorkMapper.updateVoteCountToUp(id);
	}

	@Override
	public void createQrCodeAsync(Long id) {
		executorService.execute(() -> createQrCode(id));
	}

	@Override
	public String findQrCodeUrl(Long id) {
		String qrCodeUrl = redisDao.get(Constant.VOTE_WX_HELP_SOURCE_PREFIX + id);
		if (StringUtils.isNotBlank(qrCodeUrl)) {
			return qrCodeUrl;
		}
		YgVoteWork voteWork = this.findById(id);
		if (StringUtils.isNotBlank(voteWork.getQrCode())) {
			qrCodeUrl = voteWork.getQrCode();
			redisDao.set(Constant.VOTE_WX_HELP_SOURCE_PREFIX + id, qrCodeUrl, Constant.VOTE_WX_HELP_EXPIRE_SECONDS * 1000);
			return qrCodeUrl;
		}
		return createQrCode(id);
	}

	@Override
	public List<VoteWorkListVo> findListByLeaderboard(String voteBatchCode, Integer limit) {
		return ygVoteWorkMapper.selectLeader(voteBatchCode, limit);
	}

	private String createQrCode(Long id) {
		String qrCodeUrl;
		try {
			/*qrCodeUrl = wxMpAuthorityService.findTempQrCodeUrl(Constant.VOTE_WX_HELP_SOURCE_PREFIX + id, Constant.VOTE_WX_HELP_EXPIRE_SECONDS);*/
			qrCodeUrl = wxMpAuthorityService.findQrCodeUrl(Constant.VOTE_WX_HELP_SOURCE_PREFIX + id);
			redisDao.set(Constant.VOTE_WX_HELP_SOURCE_PREFIX + id, qrCodeUrl, Constant.VOTE_REDIS_EXPIRE_SECONDS * 1000);
		} catch (WeixinException e) {
			e.printStackTrace();
			return StringUtils.isNotBlank(e.getErrorMsg()) ? e.getErrorMsg() : "二维码生成异常，请稍后重试";
		}
		YgVoteWork record = new YgVoteWork();
		record.setId(id);
		record.setQrCode(qrCodeUrl);
		record.setUpdateTime(new Date());
		record.setUpdateBy("createQrCode");
		this.update(record);

		return qrCodeUrl;
	}

}

